/*********************************************************
*Copyright (c) 2009 Rob Groves. All Rights in Pw
*@des: seesion管理器
*@name: seesion_manager
*@author: zhognsx
*@time: 2015-11-16
*********************************************************/

#ifndef _SESSION_MANAGER_H_
#define _SESSION_MANAGER_H_

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> 
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/typeof/typeof.hpp>

#include "session.h"

struct session_stu
{
	int id;
	std::string address;
	session_ptr session;
};

/* tags*/
struct sid_tag{};
struct sip_tag{};
struct sta_tag{};

/*boost 多索引容器*/
typedef boost::multi_index::multi_index_container<
	session_stu,
	boost::multi_index::indexed_by<
		boost::multi_index::ordered_unique<
		boost::multi_index::tag<sid_tag>, BOOST_MULTI_INDEX_MEMBER(session_stu, int, id)>,
		boost::multi_index::ordered_non_unique<
		boost::multi_index::tag<sip_tag>, BOOST_MULTI_INDEX_MEMBER(session_stu, std::string, address)>
	>
> session_set;

#define MULTI_MEMBER_CON(Tag) boost::multi_index::index<session_set,Tag>::type&  
#define MULTI_MEMBER_ITR(Tag) boost::multi_index::index<session_set,Tag>::type::iterator 

class session_manager
{
public:
	typedef boost::shared_lock<boost::shared_mutex> readLock;
	typedef boost::unique_lock<boost::shared_mutex> writeLock;

	session_manager(boost::asio::io_service& io_srv, int expires_time)
        :m_io_srv(io_srv), m_check_tick(io_srv), m_expires_time(expires_time)
    {
        check_connection();
    }

	~session_manager()
    {
        std::count << "session_manager delete "<< std::endl;
    }

	void add_session(session_ptr p)
    {
        writeLock lock(m_mutex);

        session_stu stu;
        stu.id = p->get_id();
        stu.address = p->get_addr_ip();
        stu.session = p;

        m_sessions.insert(stu);
    }

	template<typename Tag, typename Member>
	void del_session(Member m)
	{
		writeLock lock(m_mutex);
		if (m_sessions.empty())
		{
			return;
		}

		MULTI_MEMBER_CON(Tag) idx = boost::multi_index::get<Tag>(m_sessions);
		BOOST_AUTO(iter, idx.find(m));

		if (iter != idx.end())
		{
			idx.erase(iter);
		}
	}

	//获取容器中的第一个session  
	template<typename Tag, typename Member>
	session_ptr get_session(Member m)
	{
		readLock lock(m_mutex);
		if (m_sessions.empty())
		{
			return NULL;
		}

		MULTI_MEMBER_CON(Tag) idx = boost::multi_index::get<Tag>(m_sessions);
		BOOST_AUTO(iter, idx.find(m));
		return iter != boost::end(idx) ? iter->session : NULL;
	}

	//根据状态和sid取session  
	template<typename Member>
	session_ptr get_session_bysid(Member id, int state)
	{
		readLock lock(m_mutex);
		session_ptr ptr = get_session<sid_tag, int>(id);
		if (ptr == NULL){
			return ptr;
		}

		if (ptr->get_sta() != state){
			return NULL;
		}

		return ptr;
	}
private:
	void check_connection()
    {
	    writeLock lock(m_mutex);
    	session_set::iterator iter = m_sessions.begin();
	    while (iter != m_sessions.end())
	    {
		    //先执行断开操作，然后执行删除操作
    		if (!iter->session->socket().is_open()) //已断开，删除已断开的连接  
	    	{
		    	//iter->session->async_close();
			    iter = m_sessions.erase(iter);
    			continue;
	    	}
		    else{
			    if (iter->session->is_timeout())  //如果session已长时间没操作，则关闭  
    			{
	    			iter->session->async_close();//通过关闭触发删除session 
		    	}
	    	}
            ++iter;
        }

        m_check_tick.expires_from_now(boost::posix_time::seconds(m_expires_time));
        m_check_tick.async_wait(boost::bind(&check_connection, this));
    }

private:
	//读写锁
	boost::shared_mutex m_mutex;

	int m_expires_time; //定时检查间隔
	boost::asio::io_service& m_io_srv;
	boost::asio::deadline_timer m_check_tick; //定时器

	session_set m_sessions;
};


#endif //_SESSION_MANAGER_H_

